home *** CD-ROM | disk | FTP | other *** search
/ Best Tools for JAVA / Best Tools for JAVA.iso / JAVA_ALL / IDE / SUBARTIC / SUB_ARCT / OUTPUT / MOTIF_ST.JAV < prev    next >
Encoding:
Text File  |  1996-10-04  |  56.4 KB  |  1,681 lines

  1. package sub_arctic.output;
  2.  
  3.  
  4. import sub_arctic.input.*;
  5. import sub_arctic.lib.manager;
  6.  
  7. import java.awt.Font;
  8. import java.awt.Color;
  9. import java.awt.FontMetrics;
  10. import java.awt.Dimension;
  11. import java.awt.Rectangle;
  12. import java.util.Vector;
  13.  
  14. /**
  15.  * This is an implementation for generating the styles for a
  16.  * motifish look and feel.
  17.  * 
  18.  * @author Ian Smith
  19.  */
  20.  
  21. public class motif_style extends style  {
  22.  
  23.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  24.  
  25.   /* *********************    IMAGES      ****************/
  26.   // (generated from ppm file)
  27.   protected static int check_width = 13;
  28.   protected static int[] check_data = {
  29.     0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,
  30.     0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,
  31.     0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,
  32.     0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,
  33.     0xffffffff,0xffffffff,0xff000000,0xff000000,0xff000000,0xff000000,
  34.     0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,
  35.     0xffffffff,0xffffffff,0xffffffff,0xff000000,0xff000000,0xff000000,
  36.     0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,
  37.     0xffffffff,0xffffffff,0xffffffff,0xff000000,0xff000000,0xff000000,
  38.     0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,
  39.     0xffffffff,0xffffffff,0xffffffff,0xff000000,0xff000000,0xff000000,
  40.     0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,
  41.     0xffffffff,0xffffffff,0xffffffff,0xff000000,0xff000000,0xff000000,
  42.     0xffffffff,0xffffffff,0xff000000,0xff000000,0xff000000,0xff000000,
  43.     0xffffffff,0xffffffff,0xffffffff,0xff000000,0xff000000,0xff000000,
  44.     0xff000000,0xffffffff,0xffffffff,0xffffffff,0xff000000,0xff000000,
  45.     0xffffffff,0xffffffff,0xffffffff,0xff000000,0xff000000,0xff000000,
  46.     0xff000000,0xff000000,0xff000000,0xffffffff,0xffffffff,0xffffffff,
  47.     0xffffffff,0xffffffff,0xffffffff,0xff000000,0xff000000,0xff000000,
  48.     0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,0xffffffff,
  49.     0xffffffff,0xffffffff,0xffffffff,0xff000000,0xff000000,0xff000000,
  50.     0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,
  51.     0xff000000,0xffffffff,0xffffffff,0xff000000,0xff000000,0xff000000,
  52.     0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,
  53.     0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,
  54.     0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,
  55.     0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,
  56.     0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,0xff000000,
  57.     0xff000000,};
  58.   protected static int check_height = 13;
  59.   protected static sub_arctic.output.loaded_image _check = null;
  60.  
  61.   public static sub_arctic.output.loaded_image check() {
  62.     if (_check == null)
  63.      calculate_check();
  64.     return _check;
  65.   }
  66.  
  67.   public static void calculate_check() {
  68.     loaded_image tmp;
  69.     tmp = new sub_arctic.output.loaded_image(check_data,
  70.                          check_width,check_height);
  71.     
  72.     /* the 150 is to avoid the "black line syndrome" of feathered
  73.        images */
  74.     _check=loaded_image.
  75.       image_from_intensity_map(tmp,
  76.                    style_manager.default_color_scheme().splash(),
  77.                    150);
  78.   }
  79.  
  80.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  81.  
  82.   /* ********************* BEVELING CODE ****************/
  83.   /*
  84.    * This code generates beveled rectangles ala motif.
  85.    * 
  86.    * @param loaded_image img     the image to bevel (the contents of this image,
  87.    *                             if any, are lost).
  88.    * @param boolean      raised  should this image be draw as raised or lowered.
  89.    * @param boolean      base    should this image be draw with the base color. 
  90.    *                             as the main color (if true) or the background 
  91.    *                             color (if false).
  92.    * @param boolean      one_pix true if you want one pixel of beveling, 
  93.    *                             false if you want two.
  94.    * @param boolean      left    bevel the left edge.
  95.    * @param boolean      right   bevel the right edge.
  96.    * @param boolean      top     bevel the top edge.
  97.    * @param boolean      bottom  bevel the bottom edge.
  98.    * @param color_scheme colors  the color scheme to use for the beveling.
  99.    */
  100.   static public void bevel_rect(loaded_image img,
  101.                 boolean raised, boolean base,
  102.                 boolean one_pix,
  103.                 boolean left, boolean right, 
  104.                 boolean top, boolean bottom,
  105.                 color_scheme colors) {
  106.  
  107.     int w=img.width(), h=img.height();
  108.     drawable d=img.get_drawable();
  109.  
  110.     /* fill with the base or with the background*/
  111.     if (base) {
  112.       d.setColor(colors.base());
  113.     } else {
  114.       d.setColor(colors.background());
  115.     }
  116.     d.fillRect(0,0,w,h);
  117.  
  118.     /* put a one pixel wide strip of highlight/shadow on right ...
  119.        you want to to the bottom and right first to mimic motif */
  120.     if (raised) {
  121.       d.setColor(colors.shadow());
  122.     } else {
  123.       d.setColor(colors.highlight());
  124.     }
  125.  
  126.     /* right hand side */
  127.     if (right) {
  128.       d.fillRect(w-1,0,1,h);
  129.       /* if we are two pixels wide, do another line */
  130.       if (!one_pix) {
  131.     d.fillRect(w-2,0,1,h);
  132.       }
  133.     }
  134.  
  135.     /* put a one pixel wide strip of shadow/highlight on bottom */
  136.     if (bottom) {
  137.       d.fillRect(0,h-1,w,1);
  138.       /* if we are two pixels wide, do another line */
  139.       if (!one_pix) {
  140.     d.fillRect(0,h-2,w,1);
  141.       }
  142.     }
  143.  
  144.     /* put a one pixel wide strip of highlight/shadow along the top */
  145.     if (raised) {
  146.       d.setColor(colors.highlight());
  147.     } else {
  148.       d.setColor(colors.shadow());
  149.     }
  150.  
  151.     /* handle top */
  152.     if (top) {
  153.       d.fillRect(0,0,w,1);
  154.       /* are we two pixels? */
  155.       if (!one_pix) {
  156.     /* this is supposed to be one pixel shorter */
  157.     d.fillRect(0,1,w-1,1);
  158.       }
  159.     }
  160.  
  161.     /* same for left */
  162.     if (left) {
  163.       d.fillRect(0,0,1,h);
  164.       /* is it two pixels?*/
  165.       if (!one_pix) {
  166.     /* again, this is one pixel short of a whole line */
  167.     d.fillRect(1,0,1,h-1);
  168.       }
  169.     }
  170.   }
  171.  
  172.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  173.  
  174.   /**
  175.    * Bevel an up triangle for the top of a scrollbar.
  176.    * 
  177.    * @param loaded_image img the image you want to put the triangle in (any 
  178.    *                         contents of this rectangle are erased).
  179.    * @param color_scheme s   the color scheme to use for the drawing.
  180.    */
  181.   public static void bevel_triangle_up(loaded_image img, color_scheme s) {
  182.     int triangle_pts_x[]=new int[3];
  183.     int triangle_pts_y[]=new int[3];
  184.     int w=img.width(), h=img.height();
  185.     drawable d=img.get_drawable();
  186.  
  187.     /* put the stuff around the edge to connect it to the groove */
  188.     bevel_rect(img,false,false,true,true,true,true,false,s);
  189.  
  190.     /* start at a point two from the top in the middle */
  191.     triangle_pts_x[0]=w/2;
  192.     triangle_pts_y[0]=2;
  193.  
  194.     /* far right point is 3rd from right, 3rd from bottom */
  195.     triangle_pts_x[1]=w-3;
  196.     triangle_pts_y[1]=h-3;
  197.  
  198.     /* far left point is 3rd from left and 3rd from bottom*/
  199.     triangle_pts_x[2]=2;
  200.     triangle_pts_y[2]=h-3;
  201.  
  202.     /* draw the polygon */
  203.     d.setColor(s.base());
  204.     d.fillPolygon(triangle_pts_x, triangle_pts_y, 3);
  205.  
  206.     /* first do the shadow , just above the top point to just to the right*/
  207.     d.setColor(s.shadow());
  208.     d.drawLine(w/2,1,w-2,h-3);
  209.  
  210.     /* add a shadow line along the bottom */
  211.     d.drawLine(2,h-2,w-2,h-2);
  212.  
  213.     /* now add the left highlight from just left to just above 
  214.        the top point */
  215.     d.setColor(s.highlight());
  216.     d.drawLine(1,h-3,w/2,1);
  217.  
  218.     /* add a point just below the far left corner*/
  219.     d.drawLine(1,h-2,1,h-2);
  220.   }
  221.  
  222.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  223.  
  224.   /**
  225.    * Bevel a down triangle for the bottom of a scrollbar.
  226.    * 
  227.    * @param loaded_image img the image you want to put the triangle in (any 
  228.    *                         contents of this rectangle are erased).
  229.    * @param color_scheme s   the color scheme to use for the drawing.
  230.    */
  231.   public static void bevel_triangle_down(loaded_image img, color_scheme s) {
  232.     int triangle_pts_x[]=new int[3];
  233.     int triangle_pts_y[]=new int[3];
  234.     int w=img.width(), h=img.height();
  235.     drawable d=img.get_drawable();
  236.  
  237.     /* put the stuff around the edge to connect it to it to the groove */
  238.     bevel_rect(img,false,false,true,true,true,false,true,s);
  239.  
  240.     /*first point is 3rd from left, 3rd from top */
  241.     triangle_pts_x[0]=2;
  242.     triangle_pts_y[0]=2;
  243.  
  244.     /* second point is 3rd from right, 3rd from top */
  245.     triangle_pts_x[1]=w-3;
  246.     triangle_pts_y[1]=2;
  247.  
  248.     /* final point is in the middle 2 from bottom */
  249.     triangle_pts_x[2]=w/2;
  250.     triangle_pts_y[2]=h-3;
  251.  
  252.     /* draw the polygon */
  253.     d.setColor(s.base());
  254.     d.fillPolygon(triangle_pts_x, triangle_pts_y, 3);
  255.  
  256.     /* highlight on top */
  257.     d.setColor(s.highlight());
  258.     d.drawLine(1,1,h-2,1);
  259.  
  260.     /* highlight on left */
  261.     d.drawLine(1,2,w/2,h-2);
  262.  
  263.     /* shadow on right */
  264.     d.setColor(s.shadow());
  265.     d.drawLine(h-2,2,w/2,h-2);
  266.   }
  267.  
  268.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  269.  
  270.   /**
  271.    * Bevel a down triangle for the menu icon.
  272.    * 
  273.    * @param loaded_image img      the image you want to put the triangle in 
  274.    * @param int          x_offset the offset you want the icon at in X
  275.    * @param int          y_offset the offset you want the icon at in Y
  276.    * @param int          w        the width of the icon you want
  277.    * @param int          h        the height of the icon you want
  278.    * @param boolean      up       true if you want this icon to appear raised
  279.    * @param color_scheme s        the color scheme to use for the drawing
  280.    */
  281.   public static void bevel_menu_icon(loaded_image img, 
  282.                      int x_offset,
  283.                      int y_offset,
  284.                      int w, int h,
  285.                      boolean up,
  286.                      color_scheme s) {
  287.     
  288.     int triangle_pts_x[]=new int[3];
  289.     int triangle_pts_y[]=new int[3];
  290.     drawable d=img.get_drawable();
  291.  
  292.     /*first point is 3rd from left, 3rd from top */
  293.     triangle_pts_x[0]=x_offset+2;
  294.     triangle_pts_y[0]=y_offset+2;
  295.  
  296.     /* second point is 3rd from right, 3rd from top */
  297.     triangle_pts_x[1]=x_offset+w-3;
  298.     triangle_pts_y[1]=y_offset+2;
  299.  
  300.     /* final point is in the middle 2 from bottom */
  301.     triangle_pts_x[2]=x_offset+ (w/2);
  302.     triangle_pts_y[2]=y_offset+h-3;
  303.  
  304.     /* draw the polygon */
  305.     if (up) {
  306.       d.setColor(s.base());
  307.     } else {
  308.       d.setColor(s.background());
  309.     }
  310.     d.fillPolygon(triangle_pts_x, triangle_pts_y, 3);
  311.  
  312.     /* highlight/shadow on top */
  313.     if (up) {
  314.       d.setColor(s.highlight());
  315.     } else {
  316.       d.setColor(s.shadow());
  317.     }
  318.     d.drawLine(x_offset+1,y_offset+1,x_offset+h-2,y_offset+1);
  319.  
  320.     /* highlight on left */
  321.     d.drawLine(x_offset+1,y_offset+2,x_offset+(w/2),y_offset+h-2);
  322.  
  323.     /* shadow on right */
  324.     if (up) {
  325.       d.setColor(s.shadow());
  326.     } else {
  327.       d.setColor(s.highlight());
  328.     }
  329.     d.drawLine(x_offset+h-2,y_offset+2,x_offset+(w/2),y_offset+h-2);
  330.   }
  331.  
  332.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  333.  
  334.   /**
  335.    * Bevel a triangle for the pullright menu icon.
  336.    * @param drawable     d  the surface to bevel on.
  337.    * @param boolean      up true if you want this object to appear raised.
  338.    * @param int          x  x offset on the drawable.
  339.    * @param int          y  y offset on the drawable.
  340.    * @param color_scheme s  the color scheme to bevel in.
  341.    */
  342.   public void bevel_pullright_triangle(drawable d, boolean up,
  343.                        int x, int y, color_scheme s) {
  344.     
  345.     int triangle_pts_x[]=new int[3];
  346.     int triangle_pts_y[]=new int[3];
  347.     int w=menu_pullright_size, h=menu_pullright_size;
  348.  
  349.     /* first point is 3rd from the right in the middle */
  350.     triangle_pts_x[0]=x+ w-3;
  351.     triangle_pts_y[0]=y+ (h/2);
  352.  
  353.     /* second point is third from the top 3rd from the left */
  354.     triangle_pts_x[1]=x+2;
  355.     triangle_pts_y[1]=y+2;
  356.  
  357.     /* last point is 3rd from bottom, 3rd from left */
  358.     triangle_pts_x[2]=x+2;
  359.     triangle_pts_y[2]=y+h-3;
  360.  
  361.     /* fill in the polygon */
  362.     if (up) {
  363.       d.setColor(s.base());
  364.     } else {
  365.       d.setColor(s.background());
  366.     }
  367.     d.fillPolygon(triangle_pts_x,triangle_pts_y,3);
  368.  
  369.     /* highlight on left */
  370.     if (up) {
  371.       d.setColor(s.highlight());
  372.     } else {
  373.       d.setColor(s.shadow());
  374.     }
  375.     d.drawLine(x+1,y+1,x+1,y+h-2);
  376.  
  377.     /* highlight along top */
  378.     d.drawLine(x+2,y+1,x+w-2,y+(h/2));
  379.  
  380.     /* shadow on the bottom */
  381.     if (up) {
  382.       d.setColor(s.shadow());
  383.     } else {
  384.       d.setColor(s.highlight());
  385.     }
  386.     d.drawLine(x+w-2,y+(h/2),x+2,y+h-2);
  387.   }
  388.  
  389.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  390.  
  391.   /**
  392.    * Bevel a left triangle for the left of a scrollbar.
  393.    * 
  394.    * @param loaded_image img the image you want to put the triangle in (any 
  395.    *                         contents of this rectangle are erased).
  396.    * @param color_scheme s   the color scheme to use for the drawing.
  397.    */
  398.   public static void bevel_triangle_left(loaded_image img, color_scheme s) {
  399.     int triangle_pts_x[]=new int[3];
  400.     int triangle_pts_y[]=new int[3];
  401.     int w=img.width(), h=img.height();
  402.     drawable d=img.get_drawable();
  403.  
  404.     /* put the stuff around the edge to connect it to it to the groove */
  405.     bevel_rect(img,false,false,true,
  406.            true,false,true,true,s);
  407.  
  408.     /* first point is 3rd from right and halfway down */
  409.     triangle_pts_x[0]=2;
  410.     triangle_pts_y[0]=h/2;
  411.  
  412.     /* second point is third from top, and third from right */
  413.     triangle_pts_x[1]=w-3;
  414.     triangle_pts_y[1]=2;
  415.  
  416.     /* last point is 3rd from bottom, third from right */
  417.     triangle_pts_x[2]=w-3;
  418.     triangle_pts_y[2]=h-3;
  419.  
  420.     /* fill in the polygon */
  421.     d.setColor(s.base());
  422.     d.fillPolygon(triangle_pts_x,triangle_pts_y,3);
  423.  
  424.     /* shadow behind */
  425.     d.setColor(s.shadow());
  426.     d.drawLine(w-2,1,w-2,h-2);
  427.  
  428.     /* shadow below */
  429.     d.drawLine(1,h/2,w-2,h-2);
  430.  
  431.     /* highlight along top */
  432.     d.setColor(s.highlight());
  433.     d.drawLine(1,h/2,w-3,1);
  434.   }
  435.  
  436.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  437.  
  438.   /**
  439.    * Bevel a right triangle for the right of a scrollbar.
  440.    * 
  441.    * @param loaded_image img the image you want to put the triangle in (any 
  442.    *                         contents of this rectangle are erased).
  443.    * @param color_scheme s   the color scheme to use for the drawing
  444.    */
  445.   public static void bevel_triangle_right(loaded_image img, color_scheme s) {
  446.     int triangle_pts_x[]=new int[3];
  447.     int triangle_pts_y[]=new int[3];
  448.     int w=img.width(), h=img.height();
  449.     drawable d=img.get_drawable();
  450.  
  451.     /* put the stuff around the edge to connect it to it to the groove */
  452.     bevel_rect(img,false,false,true,false,true,true,true,s);
  453.  
  454.     /* first point is 3rd from the right in the middle */
  455.     triangle_pts_x[0]=w-3;
  456.     triangle_pts_y[0]=h/2;
  457.  
  458.     /* second point is third from the top 3rd from the left */
  459.     triangle_pts_x[1]=2;
  460.     triangle_pts_y[1]=2;
  461.  
  462.     /* last point is 3rd from bottom, 3rd from left */
  463.     triangle_pts_x[2]=2;
  464.     triangle_pts_y[2]=h-3;
  465.  
  466.     /* fill in the polygon */
  467.     d.setColor(s.base());
  468.     d.fillPolygon(triangle_pts_x,triangle_pts_y,3);
  469.  
  470.     /* highlight on left */
  471.     d.setColor(s.highlight());
  472.     d.drawLine(1,1,1,h-2);
  473.  
  474.     /* highlight along top */
  475.     d.drawLine(2,1,w-2,h/2);
  476.  
  477.     /* shadow on the bottom */
  478.     d.setColor(s.shadow());
  479.     d.drawLine(w-2,h/2,2,h-2);
  480.   }
  481.  
  482.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  483.  
  484.   /**
  485.    * This is the number of degrees of offset for this beveling
  486.    * of circles.
  487.    */
  488.   protected static int bevel_start_angle=60;
  489.  
  490.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  491.  
  492.   /** 
  493.    * Bevel a circle for use with radio buttons. This code also inserts
  494.    *
  495.    * @param loaded_image img the image to put the circle in.
  496.    * @param boolean      up  whether to bevel this image in the "up position" 
  497.    *                         (true) or  the "down position" (false).
  498.    * @param color_scheme s   the color scheme we are using.
  499.    */
  500.   public void bevel_circle(loaded_image img,boolean up,color_scheme s) {
  501.     drawable d=img.get_drawable();
  502.     int w=img.width(), h=img.height();
  503.  
  504.     /* fill with the background */
  505.     d.setColor(s.base());
  506.     d.fillRect(0,0,w,h);
  507.  
  508.     /* are we doing up? */
  509.     if (up) {
  510.       d.setColor(s.highlight());
  511.       d.drawArc(0,0,w-1,h-1,bevel_start_angle,180);
  512.       d.setColor(s.shadow());
  513.       d.drawArc(0,0,w-1,h-1,bevel_start_angle+180,180);
  514.     } else {
  515.       /* its down */
  516.       d.setColor(s.shadow());
  517.       d.drawArc(0,0,w-1,h-1,bevel_start_angle,180);
  518.       d.setColor(s.highlight());
  519.       d.drawArc(0,0,w-1,h-1,bevel_start_angle+180,180);;
  520.  
  521.       /* smaller splash circle in middle */
  522.       d.setColor(s.splash());
  523.       d.fillArc(3,3,w-6,h-6,0,360);
  524.     }
  525.   }
  526.  
  527.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  528.  
  529.   /* ****************** VERTICAL SCROLLBAR ***************/
  530.   /**
  531.    * This is how wide the vertical scrollbar is.. the thumb is 
  532.    * two pixels less.
  533.    */
  534.   static int v_scrollbar_width=15;
  535.  
  536.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  537.  
  538.   /**
  539.    * Construct three  images for a vertical scrollbar. Vertical scrollbars
  540.    * in sub_arctic are assumed to be of fixed width (although this
  541.    * is really not true for motif). Image #0 is the up image, 
  542.    * image #1 is the down image, #2 is the background image (which will
  543.    * get tiled along the length of the scrollbar) and #3 is the thumb.
  544.    * #0, #1, and #2 must be the same width and #3 be no larger than
  545.    * the other three.
  546.    * 
  547.    * @return loaded_image[] an array of 3 images for displaying a scrollbar in 
  548.    *                        your style
  549.    */
  550.   public loaded_image[] v_scrollbar_images() {
  551.     loaded_image img[]=new loaded_image[3];
  552.  
  553.     /* we are going to make them 15 pixels wide cause I like them
  554.      * that size. IES */
  555.  
  556.     //up image
  557.     img[0]=new loaded_image(v_scrollbar_width,v_scrollbar_width);
  558.  
  559.     //down image
  560.     img[1]=new loaded_image(v_scrollbar_width,v_scrollbar_width);
  561.  
  562.     //background image
  563.     img[2]=new loaded_image(v_scrollbar_width,200);
  564.  
  565.     // make the groove
  566.     bevel_rect(img[2],false,false,true /* one pixel */,
  567.            true, true, false, false, /* want left right only */
  568.            style_manager.default_color_scheme()); 
  569.  
  570.     /* make the up and down */
  571.     bevel_triangle_up(img[0],style_manager.default_color_scheme());
  572.     bevel_triangle_down(img[1],style_manager.default_color_scheme());
  573.     
  574.     /* send em home */
  575.     return img;
  576.   }
  577.  
  578.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  579.  
  580.   /**
  581.    * This method should return how far from the left edge the scrollbar
  582.    * is placed in this style. 
  583.    * @return int the "shift" of the v_scrollbar thumb to the right
  584.    */
  585.   public int v_scrollbar_thumb_shift() { return 1;}
  586.  
  587.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  588.  
  589.   /**
  590.    * This method should return an image of a thumb of a given
  591.    * height. 
  592.    * @param int h the height of the thumb in pixels
  593.    * @return loaded_image the thumb image.
  594.    */
  595.   public loaded_image v_scrollbar_thumb(int h) {
  596.  
  597.     // make the image
  598.     loaded_image img=new loaded_image(v_scrollbar_width-2,h);
  599.  
  600.     /* bevel a thumb, one pixel wide, raised */
  601.     bevel_rect(img,true /* raised */, true /* base */, 
  602.            true /* one_pix */, true /* left */,
  603.            true /* right */, true /* top */, 
  604.            true /*bottom */,style_manager.default_color_scheme());
  605.     return img;
  606.   }
  607.  
  608.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  609.  
  610.   /**
  611.    * This is the minimum height of a scrollbar thumb. 
  612.    * @return the minimum usable size of a scrollbar thumb (in pixels)
  613.    */
  614.   public int v_scrollbar_minimum_thumb_size() { return 10;}
  615.  
  616.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  617.  
  618.   /* ****************** HORIZONTAL SCROLLBAR ***************/
  619.   /**
  620.    * This is how tall the horizontal scrollbar is.. the thumb is 
  621.    * two pixels less.
  622.    */
  623.   static int h_scrollbar_height=15;
  624.  
  625.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  626.  
  627.   /**
  628.    * Construct three images for a horizontal scrollbar. Horizontal scrollbars
  629.    * in sub_arctic are assumed to be of fixed height (although this
  630.    * is really not true for motif). Image #0 is the left image, 
  631.    * image #1 is the right image, #2 is the background image (which will
  632.    * get tiled along the length of the scrollbar) and #3 is the thumb.
  633.    * #0, #1, and #2 must be the same width and #3 be no larger than
  634.    * the other three.
  635.    * 
  636.    * @return loaded_image[] an array of 3 images for displaying a scrollbar 
  637.    *                        in your style
  638.    */
  639.   public loaded_image[] h_scrollbar_images() {
  640.     loaded_image img[]=new loaded_image[3];
  641.  
  642.     /* we are going to make them 15 pixels hight cause I like them
  643.      * that size. IES */
  644.  
  645.     //up image
  646.     img[0]=new loaded_image(h_scrollbar_height,h_scrollbar_height);
  647.  
  648.     //down image
  649.     img[1]=new loaded_image(h_scrollbar_height,h_scrollbar_height);
  650.  
  651.     //background image
  652.     img[2]=new loaded_image(200,h_scrollbar_height);
  653.  
  654.     // make the groove
  655.     bevel_rect(img[2],false,false,true /* one pixel */,
  656.            false, false, true, true, /* want top/bottom only */
  657.            style_manager.default_color_scheme()); 
  658.  
  659.     /* make the up and down */
  660.     bevel_triangle_left(img[0],style_manager.default_color_scheme());
  661.     bevel_triangle_right(img[1],style_manager.default_color_scheme());
  662.     
  663.     /* send em home */
  664.     return img;
  665.   }
  666.  
  667.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  668.  
  669.   /**
  670.    * This method should return how far from the top edge the scrollbar
  671.    * is placed in this style. 
  672.    * @return int the "shift" of the v_scrollbar thumb to the right
  673.    */
  674.   public int h_scrollbar_thumb_shift() { return 1;}
  675.  
  676.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  677.  
  678.   /**
  679.    * This method should return an image of a thumb of a given
  680.    * width. 
  681.    * @param int w the width of the thumb in pixels.
  682.    * @return loaded_image the resulting thumb image.
  683.    */
  684.   public loaded_image h_scrollbar_thumb(int w) {
  685.  
  686.     // make the image
  687.     loaded_image img=new loaded_image(w,h_scrollbar_height-2);
  688.  
  689.     /* bevel a thumb, one pixel wide, raised */
  690.     bevel_rect(img,true /* raised */, true /* base */, 
  691.            true /* one_pix */, true /* left */,
  692.            true /* right */, true /* top */, 
  693.            true /*bottom */,style_manager.default_color_scheme());
  694.  
  695.     return img;
  696.   }
  697.  
  698.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  699.  
  700.   /**
  701.    * This is the minimum thumb width of a scrollbar. 
  702.    * @return the minimum usable size of a scrollbar thumb (in pixels)
  703.    */
  704.   public int h_scrollbar_minimum_thumb_size() { return 10;}
  705.  
  706.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  707.  
  708.   /* ****************** BUTTON ***************/
  709.   /**
  710.    * This is the amount of space used to bevel a button. It is
  711.    * the same in x and y.
  712.    */
  713.   private static final int bevel_space=4;
  714.  
  715.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  716.  
  717.   /**
  718.    * This is the amount of extra space needed to the right of the
  719.    * menu label to fit the menu icon.
  720.    */
  721.   private static final int menu_icon_space=14;
  722.  
  723.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  724.  
  725.   /**
  726.    * This is the size of the width and the height of the menu icon.
  727.    */
  728.   private static final int menu_icon_size=10;
  729.  
  730.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  731.  
  732.   /**
  733.    * Construct the images for a button. In the returned array, 
  734.    * img 0 is the up and img 1 is the depressed (unhappy) appearance.
  735.    *
  736.    * @param String label the string for the button.
  737.    * @param Font the font to draw the button with.
  738.    * @param int x_spacing the amount of x border (appears on left and right).
  739.    * @param int y_spacing the amount of y border (appears on top and bottom).
  740.    * @param boolean menu true if you want the appearance of a menu button.
  741.    * @return loaded_image[] resulting array of 2 images.
  742.    */
  743.   public loaded_image[] button_make_images(String label,
  744.                        Font font,
  745.                        int x_spacing,
  746.                        int y_spacing,
  747.                        boolean menu) {
  748.     
  749.     int string_width,total_width,string_height,x,y,total_height ;
  750.     int menu_width= menu ? menu_icon_space : 0, width_no_menu;
  751.  
  752.     // grab the font metrics
  753.     FontMetrics metrics=manager.get_metrics(font);
  754.     loaded_image img[]=new loaded_image[2];
  755.     drawable d;
  756.     int extra;
  757.  
  758.     /* figure out how big the string is in x and y */
  759.     string_width=metrics.stringWidth(label);
  760.     string_height=metrics.getHeight() - metrics.getLeading();
  761.  
  762.     /* get the total width without considering the menu */
  763.     width_no_menu=string_width + (2*x_spacing) + bevel_space ;
  764.  
  765.     /* compute total width and total height */
  766.     total_height= string_height + (2*y_spacing) + bevel_space;
  767.     total_width=width_no_menu + menu_width;
  768.  
  769.     /* make the images and bevel */
  770.     img[0]=new loaded_image(total_width, total_height);
  771.     img[1]=new loaded_image(total_width, total_height);
  772.  
  773.     /* .... now bevel */
  774.     bevel_rect(img[0],true /* raised */,true /* base color */,
  775.              false /*one_pix*/, true, true, true, true,
  776.              style_manager.default_color_scheme());
  777.     bevel_rect(img[1],false /* raised*/,false /* base */,
  778.              false /*one_pix */, true, true, true, true,
  779.              style_manager.default_color_scheme());
  780.  
  781.     /* where does the text go */
  782.     x=x_spacing + bevel_space/2;
  783.     y=y_spacing + metrics.getAscent() + bevel_space/2;
  784.  
  785.     /* draw the text */
  786.     d=img[0].get_drawable();
  787.     d.setFont(font);
  788.     d.setColor(style_manager.default_color_scheme().foreground());
  789.     d.drawString(label,x,y);
  790.     d=img[1].get_drawable();
  791.     d.setColor(style_manager.default_color_scheme().foreground());
  792.     d.setFont(font);
  793.     d.drawString(label,x,y);
  794.  
  795.     /* are we doing a menu? */
  796.     if (menu) {
  797.       // the last subtract is to account for the fact of being left 
  798.       // of the right border
  799.       int xshift=width_no_menu + ((menu_icon_space - menu_icon_size)/2) - 
  800.     (bevel_space/2);
  801.       int yshift=(total_height-menu_icon_size)/2;
  802.  
  803.       /* do the up icon */
  804.       bevel_menu_icon(img[0],xshift,yshift,menu_icon_size, 
  805.               menu_icon_size, true,
  806.               style_manager.default_color_scheme());
  807.  
  808.       /* do the down icon */
  809.       bevel_menu_icon(img[1],xshift,yshift,menu_icon_size, 
  810.               menu_icon_size,false,
  811.               style_manager.default_color_scheme());
  812.     }
  813.  
  814.     /* return the images */
  815.     return img;
  816.   }
  817.  
  818.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  819.  
  820.   /**
  821.    * Construct the images for a blank button.
  822.    *
  823.    * @param int     width     this is the <I>usable</I> width you desire for 
  824.    *                          this button.
  825.    * @param int     height    this is the <I>usable</I> height you desire for 
  826.    *                          this button.
  827.    * @param int     x_spacing the amount of x border (appears on left and 
  828.    *                          right).
  829.    * @param int     y_spacing the amount of y border (appears on top and 
  830.    *                          bottom).
  831.    * @param boolean menu      true if you want the appearance of a menu button
  832.    * @returns loaded_image[] resulting array of 2 images.
  833.    */
  834.   public loaded_image[] button_make_images(int width, 
  835.                        int height,
  836.                        int x_spacing,
  837.                        int y_spacing,
  838.                        boolean menu) {
  839.     loaded_image img[]=new loaded_image[2];
  840.     drawable d;
  841.     int menu_width= menu ? menu_icon_space : 0;
  842.  
  843.     /* make the space for the picture, plus the border, plus the
  844.        room for the beveling */
  845.     img[0]=new loaded_image(width + (2*x_spacing) + bevel_space 
  846.                 + menu_width ,
  847.                 height + (2*y_spacing) + bevel_space);
  848.     img[1]=new loaded_image(width + (2*x_spacing) + bevel_space +
  849.                 menu_width,
  850.                 height + (2*y_spacing) + bevel_space);
  851.                 
  852.     /* .... now bevel */
  853.     bevel_rect(img[0],true,true,false, true, true, true, true,
  854.            style_manager.default_color_scheme());
  855.     bevel_rect(img[1],false,false,false, true, true, true, true,
  856.            style_manager.default_color_scheme());
  857.  
  858.     return img;
  859.   }
  860.  
  861.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  862.  
  863.   /**
  864.    * Return the amount of shift in x required for an image to placed
  865.    * on this style of button. This does NOT including the x spacing
  866.    * but rather only the pixels that the button code isn't normally
  867.    * allowed to use (the beveling).
  868.    * @return int the amount to shift the image on a button in x
  869.    */
  870.   public int button_x_shift() {
  871.     return bevel_space/2;
  872.   }
  873.  
  874.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  875.  
  876.   /**
  877.    * Return the amount of shift in y required for an image to placed
  878.    * on this style of button. This does NOT including the y spacing
  879.    * but rather only the pixels that the button code isn't normally
  880.    * allowed to use (the beveling).
  881.    * @return int the amount to shift the image on a button in y
  882.    */
  883.   public int button_y_shift() {
  884.     return bevel_space/2;
  885.   }
  886.  
  887.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  888.  
  889.   /* ****************** RADIOBUTTON ***************/
  890.   /**
  891.    * We like motif images at 15 pixels x 15 pixels.
  892.    */
  893.   protected static int motif_radio_button_size=15;
  894.  
  895.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  896.  
  897.   /**
  898.    * Return a pair of images which give the off (img[0]) and the
  899.    * on (img[1]) appearance for a radio button. Note: For some styles, 
  900.    * this is the same appearance as a checkbox. These images should 
  901.    * be the same size.
  902.    * 
  903.    * @return loaded_image[] an array of 2 images for the off and on look of 
  904.    *                        a radio button.
  905.    */
  906.   public loaded_image[] radio_button_make_images() {
  907.     loaded_image img[]=new loaded_image[2];
  908.     img[0]=new loaded_image(motif_radio_button_size,motif_radio_button_size);
  909.     img[1]=new loaded_image(motif_radio_button_size,motif_radio_button_size);
  910.  
  911.     bevel_circle(img[0],true,style_manager.default_color_scheme());
  912.     bevel_circle(img[1],false,style_manager.default_color_scheme());
  913.     
  914.     return img;
  915.   }
  916.  
  917.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  918.  
  919.   /**
  920.    * Return a pair of transitions images for the transitions from
  921.    * (img[0]) off to on and (img[1])on to off. A style may return
  922.    * null here there will be no special transition used. 
  923.    */
  924.   public loaded_image[] radio_button_make_transitions() {
  925.     return null;
  926.   }
  927.  
  928.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  929.  
  930.   /* ****************** CHECKBOX ***************/
  931.   /**
  932.    * Return a pair of images which give the off (img[0]) and the
  933.    * on (img[1]) appearance for a checkbox. Note: For some styles, 
  934.    * this is the same appearance as a radiobutton. These images should
  935.    * be the same size. 
  936.    * 
  937.    * @return loaded_image[] an array of 2 images for the off and on look of 
  938.    *                        a checkbox
  939.    */
  940.   public loaded_image[] checkbox_make_images() {
  941.     loaded_image img[]=new loaded_image[2];
  942.     img[0]=new loaded_image(motif_radio_button_size,motif_radio_button_size);
  943.     img[1]=new loaded_image(motif_radio_button_size,motif_radio_button_size);
  944.     loaded_image orig_check, real_check;
  945.  
  946.     /* step one, is to create the boxes */
  947.     bevel_rect(img[0],true,true,true,
  948.            true,true,true,true, /* all four walls */
  949.            style_manager.default_color_scheme());
  950.     bevel_rect(img[1],false,false,true,
  951.            true,true,true,true, /* all four walls */
  952.            style_manager.default_color_scheme());
  953.  
  954.     /* now add the check */
  955.     img[1].get_drawable().drawImage(check(),1,1);
  956.  
  957.     /* send it home */
  958.     return img;
  959.   }
  960.  
  961.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  962.  
  963.   /**
  964.    * Return a pair of transitions images for the transitions from
  965.    * (img[0]) off to on and (img[1])on to off. A style may return
  966.    * null here there will be no special transition used. 
  967.    * @return loaded_image[] resulting array of 2 images.
  968.    */
  969.   public loaded_image[] checkbox_make_transitions() {
  970.     return null;
  971.   }
  972.  
  973.  
  974.   /* **********************  MISC *************************/
  975.   /** 
  976.    * This function gets called to inform the style that the
  977.    * default_color_scheme has changed. This is to allow the
  978.    * style to do any necessary recalculation of images based
  979.    * on the new color_scheme before interactors become notified
  980.    * that there is a new color_scheme.
  981.    */
  982.   public void color_scheme_changed() {
  983.     calculate_check();
  984.   }
  985.  
  986.   /* ************************ DRAWABLE ***********************/
  987.   /**
  988.    * This function gets called to force the style to set up
  989.    * a rectangular area of a drawable. The caller is requesting 
  990.    * that the drawable be prepared for further drawing by caller. 
  991.    * This is useful interactors which do their drawing in 
  992.    * draw_self_local() and/or people wishing to implement new
  993.    * interactors which can "fit in" with the style. 
  994.    * 
  995.    * @param drawable d    the drawable to prepare. It assumed that the style 
  996.    *                      will be called <I>before</I> the caller does his 
  997.    *                      drawing, so the style can and should fill the 
  998.    *                      background.
  999.    * @param int      x    the x coordinate of the top left corner of the area to
  1000.    *                      prepare.
  1001.    * @param int      y    the y coordinate of the top left corner of the area to
  1002.    *                      prepare.
  1003.    * @param int      w    the width of the area to prepare.
  1004.    * @param int      h    the height of the area of prepare.
  1005.    * @param boolean  up   if this is true the style may draw this area raised, 
  1006.    *                      if this is false the style may draw this area lowered.
  1007.    *                      The style is under no obligation to follow this hint.
  1008.    * @param boolean  fill true if the style system should fill the background.
  1009.    */
  1010.   public void drawable_prepare_rect(drawable d, int x, int y, 
  1011.                     int w, int h, boolean up, boolean fill) {
  1012.  
  1013.     color_scheme colors=style_manager.default_color_scheme();
  1014.     Color c=d.getColor();
  1015.  
  1016.     /* fill with the base or with the background*/
  1017.     if (up) {
  1018.       d.setColor(colors.base());
  1019.     } else {
  1020.       d.setColor(colors.background());
  1021.     }
  1022.  
  1023.     if (fill) {
  1024.       d.fillRect(x,y,w,h);
  1025.     }
  1026.  
  1027.     /* put a one pixel wide strip of highlight/shadow on right ...
  1028.        you want to to the bottom and right first to mimic motif */
  1029.     if (up) {
  1030.       d.setColor(colors.shadow());
  1031.     } else {
  1032.       d.setColor(colors.highlight());
  1033.     }
  1034.     d.fillRect(x+w-1,y,1,h);
  1035.  
  1036.     /* we are two pixels  wide*/
  1037.     d.fillRect(x+w-2,y,1,h);
  1038.  
  1039.     /* put a one pixel wide strip of shadow/highlight on bottom */
  1040.     d.fillRect(x,y+h-1,w,1);
  1041.     d.fillRect(x,y+h-2,w,1);
  1042.  
  1043.     /* put a one pixel wide strip of highlight/shadow along the top */
  1044.     if (up) {
  1045.       d.setColor(colors.highlight());
  1046.     } else {
  1047.       d.setColor(colors.shadow());
  1048.     }
  1049.     d.fillRect(x,y,w,1);
  1050.  
  1051.     /* this is supposed to be one pixel shorter */
  1052.     d.fillRect(x,y+1,w-1,1);
  1053.  
  1054.     /* left side */
  1055.     d.fillRect(x,y,1,h);
  1056.  
  1057.     /* again, this is one pixel short of a whole line */
  1058.     d.fillRect(x+1,y,1,h-1);
  1059.  
  1060.     /* reset the color to what it was before */
  1061.     d.setColor(c);
  1062.   }
  1063.  
  1064.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1065.  
  1066.   /**
  1067.    * This function is called to allow the caller to determine what area
  1068.    * of the drawable has been prepared by the style.
  1069.    * @return int the amount of horizontal space used by the style (XXX 
  1070.    *             assumes left/right symmetry)
  1071.    */
  1072.   public int drawable_horizontal_space() { return 2;}
  1073.  
  1074.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1075.  
  1076.   /**
  1077.    * This function is called to allow the caller to determine what area
  1078.    * of the drawable has been prepared by the style.
  1079.    * @return int the amount of vertical space used by the style (XXX 
  1080.    *             assumes up/down symmetry)
  1081.    */
  1082.   public int drawable_vertical_space() { return 2;}
  1083.  
  1084.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1085.  
  1086.   /* ************************  SCALE  ***********************/
  1087.   /**
  1088.    * This is how tall we want our scales to be.
  1089.    */
  1090.   protected int motif_scale_height=15;
  1091.  
  1092.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1093.  
  1094.   /**
  1095.    * This is how big we want our thumbs to be.
  1096.    */
  1097.   protected int motif_scale_thumb_width=30;
  1098.  
  1099.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1100.  
  1101.   /**
  1102.    * This is how far to shift the thumb.
  1103.    */
  1104.   protected int motif_scale_thumb_shift=1;
  1105.  
  1106.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1107.  
  1108.   /**
  1109.    * This function returns the image of a scale's background
  1110.    * at a given width in pixels.
  1111.    * @param int w the width of the scale in pixels.
  1112.    * @return loaded_image the image of the scale's background.
  1113.    */
  1114.   public loaded_image scale_background(int w) {
  1115.     loaded_image img=new loaded_image(w,motif_scale_height);
  1116.  
  1117.     bevel_rect(img,false,false /* dark background for darker look*/,
  1118.            true, true /*left */, true /*right */, true /*top */,
  1119.            true /* bottom */, style_manager.default_color_scheme());
  1120.     return img;
  1121.   }
  1122.  
  1123.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1124.  
  1125.   /**
  1126.    * This returns the height of the scale in pixels. We assume
  1127.    * that scales are not resizable in height.
  1128.    * @return int the height of the scale
  1129.    */
  1130.   public int scale_height() {
  1131.     return motif_scale_height;
  1132.   }
  1133.  
  1134.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1135.  
  1136.   /**
  1137.    * This returns the image of the thumb of a scale.
  1138.    * @return loaded_image the image of the thumb
  1139.    */
  1140.   public loaded_image scale_thumb() {
  1141.     loaded_image img=new loaded_image(motif_scale_thumb_width, 
  1142.                       motif_scale_height-2);
  1143.     drawable d=img.get_drawable();
  1144.     int xpos=motif_scale_thumb_width/2;
  1145.  
  1146.     bevel_rect(img,true,true /*base */,true,
  1147.            true /* left */, true /* right */, true /* top */,
  1148.            true /* bottom */, style_manager.default_color_scheme());
  1149.  
  1150.     /* now add a small "knicknack" to the thumb */
  1151.     d.setColor(style_manager.default_color_scheme().shadow());
  1152.  
  1153.     /* we draw from 1 so as to not screw up the top beveling */
  1154.     d.drawLine(xpos,1,xpos,img.height());
  1155.     d.setColor(style_manager.default_color_scheme().highlight());
  1156.     d.drawLine(xpos+1,1,xpos+1,img.height());
  1157.  
  1158.     return img;
  1159.   }
  1160.  
  1161.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1162.  
  1163.   /**
  1164.    * This returns the number of pixels the thumb is shifted
  1165.    * down from the top of the scale.
  1166.    * @return int the amount of the shift of the thumb in y
  1167.    */
  1168.   public int scale_thumb_shift() {
  1169.     return motif_scale_thumb_shift;
  1170.   }
  1171.  
  1172.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1173.  
  1174.   /**
  1175.    * This returns the amount of space on both ends which 
  1176.    * is used by the system for its beveling/color scheme.
  1177.    * If you are using a 1 pixel bevel return 1 here.
  1178.    * @return int the number of pixels to shift the display of the thumb to 
  1179.    *             the right when doing the display
  1180.    */
  1181.   public int scale_unusable_width() { return 1;};
  1182.  
  1183.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1184.  
  1185.   /* ************************   MENU   ***********************/
  1186.   /**
  1187.    * This function determines if a menu pops to the right and
  1188.    * down from an menu button interactor or if it pops directly
  1189.    * down. Return true for the (mac style) pop to the right
  1190.    * type and false for the (motif style) pop string down type.
  1191.    * @return boolean true for pop-right false for pop-down
  1192.    */
  1193.   public boolean menu_pop_right() { return false;}
  1194.  
  1195.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1196.  
  1197.   /**
  1198.    * This holds amount of space we are going to leave on the left
  1199.    * of the text to assure that we can put a small "knicknack" of
  1200.    * some kind in there if necessary.
  1201.    */
  1202.   private static int menu_space_left  = 10 ;
  1203.  
  1204.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1205.  
  1206.   /**
  1207.    * This holds amount of space we are going to leave on the right
  1208.    * of the text to assure that we can put a pullright icon in 
  1209.    * place.
  1210.    */
  1211.   private static int menu_space_right  = 12 ;
  1212.  
  1213.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1214.  
  1215.   /**
  1216.    * This is the size of the pullright menu icon.
  1217.    */
  1218.   private static int menu_pullright_size = 8;
  1219.  
  1220.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1221.  
  1222.   /**
  1223.    * This function determines the "natural" size of menu item
  1224.    * of text. Menu items can be made any width, but this expresses
  1225.    * the natural size of the object. The style object may include
  1226.    * extra space for interactors that are placed on the menu
  1227.    * item.
  1228.    * @param String s         the string to display.
  1229.    * @param Font   f         the font to display the text in.
  1230.    * @param int    x_spacing the amount of horizontal spacing desired.
  1231.    * @param int    y_spacing the amount of vertical spacing desired. 
  1232.    * @return Dimension the natural size of this menu item.
  1233.    */
  1234.   public Dimension menu_item_natural_size(String s, Font f, 
  1235.                       int x_spacing, 
  1236.                       int y_spacing) {
  1237.  
  1238.     int w,h;
  1239.     FontMetrics metrics=manager.get_metrics(f);
  1240.  
  1241.     /* just a font computation plus the motif beveling */
  1242.     w=menu_space_left + metrics.stringWidth(s) + menu_space_right +
  1243.       (2*x_spacing) + 2; /* 2 is for beveling */
  1244.     h=(metrics.getHeight()-metrics.getLeading()) + (2*y_spacing) + 2;
  1245.  
  1246.     return new Dimension(w,h);
  1247.   }
  1248.  
  1249.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1250.  
  1251.   /**
  1252.    * This function creates the two images of a menu up (unhighlighted)
  1253.    * & down (highlighted). You must supply the width and height of
  1254.    * the images you wish to create; use menu_item_natural_size()
  1255.    * to determine the natural size of menu items.  The style
  1256.    * object is expected to observe the x_spacing and y_spacing 
  1257.    * arguments, even if this forces clipping or overdrawing 
  1258.    * to occur.
  1259.    *
  1260.    * @param String  s         the string to display.
  1261.    * @param Font    f         the font to display the text in.
  1262.    * @param int     x_spacing the amount of horizontal spacing desired. 
  1263.    * @param int     y_spacing the amount of vertical spacing desired. 
  1264.    * @param int     w         width of the image.
  1265.    * @param int     h         height of the image.
  1266.    * @param boolean pullright true if you want a notation for a pullright 
  1267.    *                          image on this menu item.
  1268.    * @return loaded_image[] resulting array of 2 images.
  1269.    */
  1270.   public loaded_image[] menu_item_image(String s, Font f,
  1271.                     int x_spacing, int y_spacing,
  1272.                     int w, int h, boolean pullright) {
  1273.     
  1274.     loaded_image img[]=new loaded_image[2];
  1275.     int xoff, yoff;
  1276.     FontMetrics metrics=manager.get_metrics(f);
  1277.     drawable d;
  1278.  
  1279.     /* make the images */
  1280.     img[0]=new loaded_image(w,h);
  1281.     img[1]=new loaded_image(w,h);
  1282.  
  1283.     /* bevel the rectangles, first is flat in base and the 
  1284.        second a down in background */
  1285.     bevel_rect(img[0],true /* up */,true /* base */, true /*one pix */,
  1286.            false /* no left */, false /* no right */,
  1287.            false /* no top */, false /* no bottom */,
  1288.            style_manager.default_color_scheme());
  1289.     bevel_rect(img[1],false /* down */,false /* bkgrnd */, true /*one pix */,
  1290.            true, true, true, true,
  1291.            style_manager.default_color_scheme());
  1292.     
  1293.     /* place the text on the up */
  1294.     xoff=x_spacing + menu_space_left + 1 /* 1 is the bevel  */;
  1295.     yoff=y_spacing + metrics.getAscent() + 1 /* 1 is bevel */;
  1296.     d=img[0].get_drawable();
  1297.     d.setFont(f);
  1298.     d.setColor(style_manager.default_color_scheme().foreground());
  1299.     d.setFont(f);
  1300.     d.drawString(s,xoff,yoff);
  1301.     if (pullright) {
  1302.       bevel_pullright_triangle(d,true /*up */,
  1303.                    w-x_spacing-menu_pullright_size,
  1304.                    (h-menu_pullright_size)/2,
  1305.                    style_manager.default_color_scheme());
  1306.     
  1307.                    
  1308.     }
  1309.  
  1310.     /* do the down */
  1311.     d=img[1].get_drawable();
  1312.     d.setFont(f);
  1313.     d.setColor(style_manager.default_color_scheme().foreground());
  1314.     d.drawString(s,xoff,yoff);
  1315.  
  1316.     /* do we have a pullright? */
  1317.     if (pullright) {
  1318.       bevel_pullright_triangle(d,false /*down */,
  1319.                    w-x_spacing-menu_pullright_size,
  1320.                    (h-menu_pullright_size)/2,
  1321.                    style_manager.default_color_scheme());
  1322.     
  1323.                    
  1324.     }
  1325.  
  1326.     /* send the images back */
  1327.     return img;
  1328.   }
  1329.  
  1330.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1331.  
  1332.   /**
  1333.    * How tall is a separator.
  1334.    */
  1335.   private static final int separator_height=2;
  1336.  
  1337.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1338.  
  1339.   /**
  1340.    * Return the image of a menu separator. The style may choose
  1341.    * to return a zero height object for this separator if it does
  1342.    * not allow menu separators.
  1343.    * @return loaded_image the image of the separator.
  1344.    */
  1345.   public loaded_image menu_item_separator(int w) {
  1346.  
  1347.     loaded_image img=new loaded_image(w,separator_height);
  1348.     drawable d=img.get_drawable();
  1349.     d.setColor(style_manager.default_color_scheme().shadow());
  1350.     d.drawLine(0,0,w,0);
  1351.     d.setColor(style_manager.default_color_scheme().highlight());
  1352.     d.drawLine(0,1,w,1);
  1353.  
  1354.     return img;
  1355.   }
  1356.  
  1357.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1358.  
  1359.   /* ************************ MENUBAR ***********************/
  1360.  
  1361.   /** left and right edge spacing */
  1362.   private static final int menubar_edge_space=10;
  1363.  
  1364.   /** space between menu buttons */
  1365.   private static final int menubar_inter_child_space=20;
  1366.  
  1367.   /** space above menu bar items */
  1368.   private static final int menubar_top_space=5;
  1369.  
  1370.   /** space below the menu bar items */
  1371.   private static final int menubar_bottom_space=5;
  1372.  
  1373.   /**
  1374.    * This is the most complex of the style functions, and the one that
  1375.    * certainly leaves the most room for improvement. The caller of 
  1376.    * this function is requesting several things. First, an image to
  1377.    * display for a menu bar of a given width. Second, a set of 
  1378.    * rectangles that tell the menubar infrastructure what regions of
  1379.    * the menu bar are "hot."  Finally, the caller is asking for
  1380.    * a set of images that corresponds to the "depressed" images 
  1381.    * of each hotspt.  <P>
  1382.    *
  1383.    * The caller supplies the style system with two vectors. Each
  1384.    * vector must contain <I>only</I> strings or loaded_images. (If
  1385.    * the loaded images are taller than the height of the font supplied,
  1386.    * they will be clipped.) The caller is responsible for making
  1387.    * sure the types of the objects are correct. The style system will
  1388.    * create it set of hot spots and images with the first vector
  1389.    * occupying the "normal" or left positions and the the second
  1390.    * vector occupying the "special" or right positions. These vectors
  1391.    * may not be null, although they may be empty.
  1392.    *
  1393.    * @param Vector left           this should be a non-null (but possibly empty)
  1394.    *                              vector of strings and images. Items in this 
  1395.    *                              vector will be replaced with loaded_images 
  1396.    *                              representing that items "down" image. These 
  1397.    *                              items will appear on the left of the menu 
  1398.    *                              bar, in the order supplied.
  1399.    * @param Vector right          this should be a non-null (but possibly empty)
  1400.    *                              vector of strings and images. Items in this 
  1401.    *                              vector will be replaced with loaded_images 
  1402.    *                              representing that items "down" image. These 
  1403.    *                              items will appear on the right of the 
  1404.    *                              menubar in the order supplied (last in the 
  1405.    *                              Vector being the rightmost).
  1406.    * @param int    width          width of the menubar in pixels (items which 
  1407.    *                              don't fit on the menubar will be clipped)
  1408.    * @param Font   font           the font to use for rendering strings. If 
  1409.    *                              you have a menubar which has only images on 
  1410.    *                              it, the menu bar is still the height of this 
  1411.    *                              font.
  1412.    * @param Vector left_hotspots  the caller should pass a non-null but empty 
  1413.    *                              vector which will be filled in which 
  1414.    *                              Rectangle objects indicating the positions 
  1415.    *                              of the objects in the left vector on the 
  1416.    *                              returned image.
  1417.    * @param Vector right_hotspots the caller should pass a non-null but empty 
  1418.    *                              vector which will be filled in which 
  1419.    *                              Rectangle objects indicating the positions 
  1420.    *                              of the objects in the right vector on the 
  1421.    *                              returned image.
  1422.    * @return loaded_image the image of the menu bar at the selected width
  1423.    */
  1424.   public loaded_image make_menubar_images(Vector left_items,
  1425.                        Vector right_items,
  1426.                        int width,
  1427.                        Font font,
  1428.                        Vector left_hotspots,
  1429.                        Vector right_hotspots) {
  1430.     /* figure out how tall the bar is */
  1431.     FontMetrics metrics=manager.get_metrics(font);
  1432.     int height,i,left=menubar_edge_space,right,item_width,farthest_right=0;
  1433.     loaded_image menubar,image=null,depressed;
  1434.     drawable d;
  1435.     String text=null;
  1436.     Object o;
  1437.     Rectangle rect;
  1438.  
  1439.     /* we are just going to disallow menubars if they get too small */
  1440.     if (width<4*menubar_edge_space) {
  1441.       return null;
  1442.     }
  1443.  
  1444.     /* set the size of the hotspot objects */
  1445.     left_hotspots.setSize(left_items.size());
  1446.     right_hotspots.setSize(right_items.size());
  1447.  
  1448.     /* how tall is the object's font */
  1449.     height=metrics.getHeight() - metrics.getLeading();
  1450.  
  1451.     /* add in the spacing */
  1452.     height+=menubar_top_space + menubar_bottom_space;
  1453.  
  1454.     /* make the menubar image */
  1455.     menubar=new loaded_image(width,height);
  1456.  
  1457.     /* bevel it */
  1458.     bevel_rect(menubar, true, true, false /* two pixels on bars */,
  1459.            true, true, true, true, style_manager.default_color_scheme());
  1460.  
  1461.     /* compute area for left objects */
  1462.     for (i=0; i<left_items.size(); ++i) {
  1463.  
  1464.       /* figure out how wide this item is... first get the item */
  1465.       o=left_items.elementAt(i);
  1466.  
  1467.       /* is it string or image? */
  1468.       if (o instanceof String) {
  1469.     /* string, so use the font metrics to figure out size */
  1470.     text=(String)o;
  1471.     item_width=metrics.stringWidth(text) + menubar_inter_child_space;
  1472.       } else {
  1473.     /* we assume this cause we figure the layer above us will check */
  1474.     /* convert to image and just ask its size*/
  1475.     image=(loaded_image)o;
  1476.     item_width=image.width() + menubar_inter_child_space;
  1477.       }
  1478.  
  1479.       /* is the left edge past the end of the menu bar? */
  1480.       if (left>menubar.width()) {
  1481.     /* set the image of this to be null */
  1482.     left_items.setElementAt(null,i);
  1483.     left_hotspots.setElementAt(null,i);
  1484.  
  1485.     /* make sure we don't end up with stuff from the right part 
  1486.        hosing us */
  1487.     farthest_right=left;
  1488.  
  1489.     /* next iter */
  1490.     continue;
  1491.       }
  1492.  
  1493.       /* normal case... the object is going to at least partially fit */
  1494.       /* where is the right edge */
  1495.       right=left+item_width;
  1496.  
  1497.       /* make sure the area doesn't go past the edge */
  1498.       if (right>menubar.width()) {
  1499.     right=menubar.width();
  1500.       }
  1501.  
  1502.       /* we now have a new farthest right */
  1503.       farthest_right=right;
  1504.  
  1505.       /* build the image of the depressed button  */
  1506.       depressed=new loaded_image(right-left,height-(2*menubar_image_shift()));
  1507.  
  1508.       /* bevel it down */
  1509.       bevel_rect(depressed, false /* lowered */, false /* background */,
  1510.          true /* one pix */, true, true, true, true,
  1511.          style_manager.default_color_scheme());
  1512.  
  1513.       /* draw on the main menubar */
  1514.       d=menubar.get_drawable();
  1515.  
  1516.       /* is it text or not? */
  1517.       if (o instanceof String) {
  1518.     d.setFont(font);
  1519.     d.drawString(text,left + (menubar_inter_child_space/2),
  1520.              menubar_top_space + metrics.getAscent());
  1521.       }  else {
  1522.     /* its an image, figure out where to put its top left corner */
  1523.     d.drawImage(image,left + (menubar_inter_child_space/2),
  1524.             menubar_top_space);
  1525.       }
  1526.  
  1527.       /* draw on the down image */
  1528.       d=depressed.get_drawable();
  1529.  
  1530.       /* is it text or not? */
  1531.       if (o instanceof String) {
  1532.     d.setFont(font);
  1533.     d.drawString(text,menubar_inter_child_space/2,
  1534.              (menubar_top_space + metrics.getAscent()) -
  1535.              (menubar_image_shift()));
  1536.       }  else {
  1537.     /* its an image, figure out where to put its top left corner */
  1538.     d.drawImage(image,menubar_inter_child_space/2,
  1539.             menubar_top_space);
  1540.       }
  1541.  
  1542.       /* put the depressed image in the slot for the object */
  1543.       left_items.setElementAt(depressed,i);
  1544.  
  1545.       /* put the coordinates of this guy in his rectangle */
  1546.       rect=new Rectangle(left,0,right-left,height);
  1547.       left_hotspots.setElementAt(rect,i);
  1548.  
  1549.       /* reset the left coordinate */
  1550.       left=right+1;
  1551.     }
  1552.  
  1553.     /*
  1554.      * Walk the right hand set of objects
  1555.      */
  1556.     /* initialize right to be the right hand side */
  1557.     right=width-menubar_edge_space;
  1558.  
  1559.     /* walk along the right_items data structure in reverse order */
  1560.     for (i=right_items.size()-1; i>=0; --i) {
  1561.  
  1562.       /* figure out how wide this item is... first get the item */
  1563.       o=right_items.elementAt(i);
  1564.  
  1565.       /* is it string or image? */
  1566.       if (o instanceof String) {
  1567.     /* string, so use the font metrics to figure out size */
  1568.     text=(String)o;
  1569.     item_width=metrics.stringWidth(text) + menubar_inter_child_space;
  1570.       } else {
  1571.     /* we assume this cause we figure the layer above us will check */
  1572.     /* convert to image and just ask its size*/
  1573.     image=(loaded_image)o;
  1574.     item_width=image.width() + menubar_inter_child_space;
  1575.       }
  1576.  
  1577.       /* compute the left edge of the object */;
  1578.       left=right-item_width;
  1579.  
  1580.       /* is it too far over to be displayed at all? */
  1581.       if ((right<0)|| (right<farthest_right) /* of the left objects */) {
  1582.     /* nothing to do except bail out */
  1583.     /* set the image of this to be null */
  1584.     right_items.setElementAt(null,i);
  1585.     right_hotspots.setElementAt(null,i);
  1586.  
  1587.     /* next iter */
  1588.     continue;
  1589.       }
  1590.  
  1591.       /* it will at least partially fit, so make sure it isn't partial */
  1592.       if ((left<0) || (left<farthest_right)) {
  1593.     if (left<0) left=0;
  1594.     if (left<farthest_right) left=farthest_right;
  1595.       }
  1596.  
  1597.       /* build the image of the depressed button  */
  1598.       depressed=new loaded_image(right-left,height-(2*menubar_image_shift()));
  1599.  
  1600.       /* bevel it down */
  1601.       bevel_rect(depressed, false /* lowered */, false /* background */,
  1602.          true /* one pix */, true, true, true, true,
  1603.          style_manager.default_color_scheme());
  1604.  
  1605.       /* draw on the main menubar */
  1606.       d=menubar.get_drawable();
  1607.  
  1608.       /* is it text or not? */
  1609.       if (o instanceof String) {
  1610.     d.setFont(font);
  1611.     d.drawString(text,left + (menubar_inter_child_space/2),
  1612.              menubar_top_space + metrics.getAscent());
  1613.       }  else {
  1614.     /* its an image, figure out where to put its top left corner */
  1615.     d.drawImage(image,left + (menubar_inter_child_space/2),
  1616.             menubar_top_space);
  1617.       }
  1618.  
  1619.       /* draw on the down image */
  1620.       d=depressed.get_drawable();
  1621.  
  1622.       /* is it text or not? */
  1623.       if (o instanceof String) {
  1624.     d.setFont(font);
  1625.     d.drawString(text,menubar_inter_child_space/2,
  1626.              (menubar_top_space + metrics.getAscent()) - 
  1627.              menubar_image_shift());
  1628.       }  else {
  1629.     /* its an image, figure out where to put its top left corner */
  1630.     d.drawImage(image,menubar_inter_child_space/2,
  1631.             menubar_top_space);
  1632.       }
  1633.  
  1634.       /* put the depressed image in place */
  1635.       right_items.setElementAt(depressed,i);
  1636.  
  1637.       /* put the coordinates of this guy in his rectangle */
  1638.       rect=new Rectangle(left,0,right-left,height);
  1639.       right_hotspots.setElementAt(rect,i);
  1640.  
  1641.       /* update the right coordinate */
  1642.       right=left-1;
  1643.     }
  1644.  
  1645.     /* done with everything, return the menubar */
  1646.     return menubar;
  1647.   }
  1648.  
  1649.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1650.  
  1651.   /**
  1652.    * This parameter controls how far down the images resulting from
  1653.    * a menubar should be shifted down (in their hotspot) to compensate
  1654.    * for potential style system beveling.
  1655.    *
  1656.    * @return int the number of pixels the depressed images should be shifted 
  1657.    *             down in their hotspot when the button is depressed.
  1658.    */
  1659.   public int menubar_image_shift() {
  1660.     return 2; /* two pixel bevel on menubars */
  1661.   }
  1662.  
  1663.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  1664. }
  1665. /*=========================== COPYRIGHT NOTICE ===========================
  1666.  
  1667. This file is part of the subArctic user interface toolkit.
  1668.  
  1669. Copyright (c) 1996 Scott Hudson and Ian Smith
  1670. All rights reserved.
  1671.  
  1672. The subArctic system is freely available for most uses under the terms
  1673. and conditions described in 
  1674.   http://www.cc.gatech.edu/gvu/ui/sub_arctic/sub_arctic/doc/usage.html 
  1675. and appearing in full in the lib/interactor.java source file.
  1676.  
  1677. The current release and additional information about this software can be 
  1678. found starting at: http://www.cc.gatech.edu/gvu/ui/sub_arctic/
  1679.  
  1680. ========================================================================*/
  1681.